<head>
	<link rel="stylesheet" href="./main.css?ver=40" />
	<style>
		.container {
			max-width: min(80%,875px);
			width: fit-content;
			margin: 0 auto;
		}

		h1 {
			margin-top: 1em;
			margin-bottom: 1em;
			padding: 10px;
		}

		a {
			color: #00538c;
		}
		
		a:link {
			color: #00538c;
		}
		
		a:visited {
			color: #00538c;
		}
		
		.card {
			margin: 10px;
			box-shadow: 0 4px 8px 0 rgb(0 0 0 / 10%);
			background-color: #ddd;
			color: black;
			margin-bottom: 1.5em;
		}

		.card>div {
			padding: 10px;
		}

		.card h2 {
			font-size: 1.5em;
			padding: 10px;
			background-color: #457b9d;
			color: white;
			border-bottom: 2px solid #3b6a87;
		}

		small {
			font-style: italic;
			display: block;
			margin-left: 1em;
		}

		span.warning {
			color: rgb(212, 191, 0);
		}

		input {
			padding: 10px;
		}

		video {
			max-width: 640px;
			max-height: 360px;
			padding: 20px;
		}

		audio {
			max-width: 640px;
			max-height: 360px;
			padding: 20px;
		}

		div#processing {
			display: none;
			justify-content: center;
			place-items: center;
			position: absolute;
			inset: 0;
			font-size: 1.5em;
			font-weight: bold;
			background: #141926;
			flex-direction: column;
		}
	</style>
</head>

<body style='color:white'>
	<div id="header">
		<a id="logoname" href="./" style="text-decoration: none; color: white; margin: 2px">
			<span data-translate="logo-header">
				<font id="qos">V</font>DO.Ninja
			</span>
		</a>
	</div>
	<div class="container">
		<div id="info">
			<h1>Web-based Media Conversion Tools</h1>
			<div class="card">
				<h2>WebM (or MKV/FLV) to MP4 (fixed 1280x720 resolution) <span class='warning'>(very slow!)</span></h2>
				<div>
					<small>The same as: <i>fmpeg -i input.webm -vf scale="1280:720" output.mp4</i></small>
					<input type="file" accept=".mkv, .flv, .webm" id="uploader" title="Convert WebM to MP4">
				</div>
			</div>
			<div class="card">
				<h2>WebM to MP4 files (no transcoding, *attempts* to force high resolutions)</h2>
				<div>
					<small>The same as:  <i>ffmpeg.exe -i concat:"<a href='cap.webm'  target="_blank">cap.webm</a>|input.webm" -safe 0 -c copy -avoid_negative_ts 1 -strict experimental output.mp4</i></small>
					<input type="file" id="uploader3" accept=".webm" title="Convert WebM to MP4">
				</div>
			</div>
			<div class="card">
				<h2>WebM to Audio-only files (opus or wav)</h2>
				<div>
					<small>The same as:  <i>fmpeg -i input.webm -vn -acodec copy output.wav</i></small>
					<input type="file" id="uploader4" accept=".webm" title="Convert WebM to OPUS (or WAV)">
				</div>
			</div>
			<div class="card">
				<h2>MKV (or FLV/WebM) to MP4 (no transcoding)</h2>
				<div>
					<small>The same as:  <i>fmpeg -i INPUTFILE -vcodec copy -acodec copy output.mp4</i></small>
					<input type="file" id="uploader2" accept=".mkv, .flv, .webm" title="Convert MKV (or FLV) to MP4">
				</div>
			</div>
			<div class="card">
				<h2>Having problems?</h2>
				<div>
					For larger files, over 2-gigabytes in size, the browser may not be able to properly process the video in memory.
				</div>
				<div>
					Please consider using FFmpeg <a href='https://ffmpeg.org/download.html' target="_blank">[get it free here]</a> to run these processes from the command-line instead. The corresponding commands are provided above, where you need to replace input.webm with your own file.
				</div>
				<div>
					Other users who find FFmpeg too challenging have had luck using the graphical <a href="https://handbrake.fr/"  target="_blank">Handbrake</a> application instead.
				</div>
			</div>
			<div id="processing">
				<span id="message"></span>
				<video id="player" controls style="display:none"></video>
				<audio id="player2" controls style="display:none"></audio>
			</div>
		</div>

    <script>
      if (window.location.hostname.indexOf("vdo.ninja") == 0) {
        window.location = window.location.href.replace("vdo.ninja","isolated.vdo.ninja"); // FFMPEG requires an isolated domain.
      }
    </script>

		<script src="./thirdparty/ffmpeg.min.js"></script>
		<script>

			window.onerror = function backupErr(errorMsg, url=false, lineNumber=false) {
				console.error(errorMsg);
				alert("An error occured.\n\nIf your file is larger than 2-GB, you may need to run the FFmpeg commands locally or use Handbrake instead.");
				return false;
			};


			function download(data, filename) {
				const blob = new Blob([data.buffer]);
				const url = window.URL.createObjectURL(blob);
				const a = document.createElement('a');
				a.style.display = 'none';
				a.href = url;
				a.download = filename;
				document.body.appendChild(a);
				a.click();
				setTimeout(() => {
					document.body.removeChild(a);
					window.URL.revokeObjectURL(url);
				}, 100);
			}

			const { createFFmpeg, fetchFile } = FFmpeg;
			const ffmpeg = createFFmpeg({ log: true });

			const transcode = async ({ target: { files } }) => {
				const { name } = files[0];
				console.log(files[0]);
				if (files[0].size>2147483648){
					alert("Warning: The largest file size currently supported is 2-GB.\n\nFor larger files, please instead consider using the FFmpeg commands locally or use Handbrake. ");
					return;
				}
				document.getElementById('uploader').style.display = "none";
				document.getElementById('uploader2').style.display = "none";
				document.getElementById('uploader3').style.display = "none";
				document.getElementById('message').innerText = "Transcoding file... this will take a while";
				document.getElementById('processing').style.display = 'flex';
				await ffmpeg.load();
				ffmpeg.FS('writeFile', name, await fetchFile(files[0]));
				await ffmpeg.run('-i', name, '-vf', 'scale=1280:720', 'output.mp4');
				const data = ffmpeg.FS('readFile', 'output.mp4');
				const video = document.getElementById('player');
				video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
				video.style.display = "block";
				document.getElementById('message').innerText = "Operation Done. Play video or download it.";
			}
			
			const transmux = async ({ target: { files } }) => {
				const { name } = files[0];
				if (files[0].size>2147483648){
					alert("Warning: The largest file size currently supported is 2-GB.\n\nFor larger files, please instead consider using the FFmpeg commands locally or use Handbrake. ");
					return;
				}
				document.getElementById('uploader').style.display = "none";
				document.getElementById('uploader2').style.display = "none";
				document.getElementById('uploader3').style.display = "none";
				document.getElementById('message').innerText = "Transcoding file... this will take a while";
				document.getElementById('processing').style.display = 'flex';
				await ffmpeg.load();
				ffmpeg.FS('writeFile', name, await fetchFile(files[0]));
				await ffmpeg.run('-i', name, '-vcodec', 'copy', '-acodec', 'copy', 'output.mp4');
				const data = ffmpeg.FS('readFile', 'output.mp4');
				const video = document.getElementById('player');
				video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));

				video.style.display = "block";
				document.getElementById('message').innerText = "Operation Done. Play video or download it.";
			}

			const force1080 = async ({ target: { files } }) => {
				const { name } = files[0];
				if (files[0].size>2147483648){
					alert("Warning: The largest file size currently supported is 2-GB.\n\nFor larger files, please instead consider using the FFmpeg commands locally or use Handbrake. ");
					return;
				}
				const sourceBuffer = await fetch("./media/cap.webm").then(r => r.arrayBuffer());
				document.getElementById('uploader').style.display = "none";
				document.getElementById('uploader2').style.display = "none";
				document.getElementById('uploader3').style.display = "none";
				document.getElementById('message').innerText = "Tweaking file... this will take a moment";
				document.getElementById('processing').style.display = 'flex';
				await ffmpeg.load();
				ffmpeg.FS('writeFile', name, await fetchFile(files[0]));
				ffmpeg.FS("writeFile", "cap.webm", new Uint8Array(sourceBuffer, 0, sourceBuffer.byteLength));

				await ffmpeg.run("-i", "concat:cap.webm|" + name, "-safe", "0", "-c", "copy", "-avoid_negative_ts", "1", "-strict", "experimental", "output.mp4");
				const data = ffmpeg.FS('readFile', 'output.mp4');
				const video = document.getElementById('player');
				video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
				video.style.display = "block";
				document.getElementById('message').innerText = "Operation Done. Play video or download it.";
				document.getElementById('processing').style.display = 'flex';
			}

			const convertToAudioOnly = async ({ target: { files } }) => {
				const { name } = files[0];
				if (files[0].size>2147483648){
					alert("Warning: The largest file size currently supported is 2-GB.\n\nFor larger files, please instead consider using the FFmpeg commands locally or use Handbrake. ");
					return;
				}
				document.getElementById('message').innerText = "Transcoding file... this will take a while";
				document.getElementById('processing').style.display = 'flex';
				await ffmpeg.load();
				ffmpeg.FS('writeFile', name, await fetchFile(files[0]));
				const video = document.getElementById('player');

				await ffmpeg.run('-i', name, '-vn', '-acodec', 'copy', 'output.opus');
				const data = ffmpeg.FS('readFile', 'output.opus');

				console.log(data.buffer.byteLength);
				if (data.buffer.byteLength) {
					video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'audio/opus' }));
					download(data, name.split(".")[0] + ".opus");
				} else {
					await ffmpeg.run('-i', name, '-vn', '-acodec', 'copy', 'output.wav');
					const data2 = ffmpeg.FS('readFile', 'output.wav');
					video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'audio/pcm' }));
					download(data2, name.split(".")[0] + ".wav");
				}

				video.style.display = "block";
				document.getElementById('message').innerText = "Operation Done. Play audio or download it.";
				document.getElementById('processing').style.display = 'flex';
			}

			document.getElementById('uploader').addEventListener('change', transcode);
			document.getElementById('uploader2').addEventListener('change', transmux);
			document.getElementById('uploader3').addEventListener('change', force1080);
			document.getElementById('uploader4').addEventListener('change', convertToAudioOnly);
		</script>
</body>